from django.db import models
from django.contrib.postgres.fields import JSONField

from apps.storage.models.material import MaterialCategory
from apps.storage.models.data import DataMeta
from apps.storage.models.template import Template

from .misc import *
# Create your models here.

class BasicDoc(models.Model):
    """
    下载量、访问量的统计基类
    """
    views = models.IntegerField(default=0)
    downloads = models.IntegerField(default=0)

    def inc_view(self):
        self.views += 1
        self.save()

    def inc_dl(self):
        self.downloads += 1
        self.save()

    class Meta:
        abstract = True


class DataCounter(BasicDoc):
    """
    每一条数据的统计内容
    """
    ref = models.OneToOneField(DataMeta, on_delete=models.CASCADE)

    category = models.ForeignKey(MaterialCategory, on_delete=models.SET_NULL, null=True)

    def to_list(self) -> list:
        return [self.views, self.downloads]

    @staticmethod
    def get_unique(target: DataMeta):
        obj, created = DataCounter.objects.get_or_create(ref=target, category=target.category)
        return obj


class ClassCounter(BasicDoc):
    """
    每个分类的统计内容
    只保存叶节点的统计内容。
    """
    ref = models.OneToOneField(MaterialCategory, on_delete=models.CASCADE)

    def to_list(self):
        template_count = Template.objects.filter(category=self.ref).count()
        data_count = DataMeta.objects.filter(category=self.ref).count()
        return [self.views, self.downloads, template_count, data_count]

    @staticmethod
    def get_unique(target: MaterialCategory):
        # assert target.leaf is True
        obj, created = ClassCounter.objects.get_or_create(ref=target)
        return obj


def check_date(beg: int, end: int) -> bool:
    """
    检查年月是否合法
    :param beg: 起始年月
    :param end: 终点年月
    :return:
    """
    beg_month = beg % 100
    end_month = end % 100
    beg_year = beg / 100
    end_year = end / 100

    if not (0 < beg_month < 13 and 0 < end_month < 13):
        return False
    if not (beg_year > 0 and end_year > 0):
        return False
    if beg > end:
        return False
    return True


class ClassTrend(models.Model):
    """
    记录每一个分类的趋势数据
    只有叶子节点存在这种记录
    全局记录和非叶子节点的记录在请求时计算并缓存
    """
    ref = models.OneToOneField(MaterialCategory, on_delete=models.CASCADE)

    record = JSONField(default=dict)

    def get_trend_by_date(self, beg: int, end: int) -> list:
        if not check_date(beg, end):
            return []
        else:
            result = []
            for m in months(beg // 100, beg % 100, end // 100, end % 100):

                try:
                    result.append({'date': m, 'data': self.record[str(m)]})
                except KeyError:
                    result.append({'date': m, 'data': [0, 0, 0, 0]})
            return result

    @staticmethod
    def get_unique(target: MaterialCategory):
        # assert target.leaf is True
        obj, created = ClassTrend.objects.get_or_create(ref=target)
        return obj
